#include "nw_protocol.h"
#include "nw_client_struct.h"
#include "sm4.h"
#include "utility.h"
#include <string.h>
#include <stdlib.h>

struct t_nw_promsg *_nwpromsg;

struct t_upcmdcot
{
    uint8 cmd;
    uint16 cot;
};

//主动为6 E_CAUSE_ACT
//应答为7 E_CAUSE_ACT_CON
static struct t_upcmdcot upcmdcotbuf[] =
{
    {E_CMD_UP_CHARGE_AUTH,E_CAUSE_ACT},// = 1,  //鉴权数据(主动)
    {E_CMD_UP_CHARGE_RECORD,E_CAUSE_ACT},// = 2, //充电记录上传数据(主动)
    {E_CMD_UP_RANDOM_NUM,E_CAUSE_ACT},//=3, //交易取随机数(主动)
    {E_CMD_UP_COST_MODE_REQ,E_CAUSE_ACT},//=4, //请求下发计费模型数据(主动)
    {E_CMD_UP_COST_MODE_ACK,E_CAUSE_ACT_CON},//=5, //下发计费模型结果数据(应答)
    {E_CMD_UP_DOUBLE_AUTH_DATA_REQ,E_CAUSE_ACT},//=6, //双向认证终端发起双向认证上行数据(主动)
    {E_CMD_UP_DOUBLE_AUTH_DATA_UP,E_CAUSE_ACT_CON},//=7, //双向认证终端上送认证上行数据(应答)
    {E_CMD_UP_ESAM_KEY_NORMAL,E_CAUSE_ACT},//=8, //ESAM密钥更新中基本数据（主动）
    {E_CMD_UP_ESAM_FIELD1_ACK,E_CAUSE_ACT_CON},//=9, //ESAM密钥文件1更新成功数据(应答)
    {E_CMD_UP_ESAM_FIELD2_ACK,E_CAUSE_ACT_CON},//=10, //ESAM密钥文件2更新成功数据(应答)
    {E_CMD_UP_BLACKLIST,E_CAUSE_ACT_CON},// = 11, //黑名单下发时上行数据(应答)
    {E_CMD_UP_DOUBLE_AUTH_DATA_ACK,E_CAUSE_ACT_CON},//=12, //双向认证终端认证运营管理系统上行数据（应答）
    {E_CMD_UP_REMOTE_START_CHARGE,E_CAUSE_ACT_CON},//=13, //远程启动充电执行结果(应答)
    {E_CMD_UP_REMOTE_STOP_CHARGE,E_CAUSE_ACT_CON},//=14, //远程终止充电执行结果（应答）
    {E_CMD_UP_REMOTE_POWER_SET,E_CAUSE_ACT_CON},//=15, //远程功率控制结果（应答）
    {E_CMD_UP_REMOTE_UPDATE,E_CAUSE_ACT_CON},//=16, //远程升级启动命令接收结果(应答)
    {E_CMD_UP_CHARGING_DATA,E_CAUSE_ACT},//=17, //充电过程中上传数据(主动)
    {E_CMD_UP_DEV_PARA_SET_ACK,E_CAUSE_ACT_CON},//=18, //充电设备上报参数设置结果(应答)
    {E_CMD_UP_SM4_KEY_UPDATE_ACK,E_CAUSE_ACT_CON},//=19, //SM4密钥更新结果（应答）
    {E_CMD_UP_REMOTE_CALL_RECORD_ACK,E_CAUSE_ACT_CON},// = 20,//远程召唤充电记录结果通知（应答）
    {E_CMD_UP_REMOTE_UPDATE_USER_REMAIN_ACK,E_CAUSE_ACT_CON},// = 21,//远程更新用户帐户余额通知（应答）
    {E_CMD_UP_REMOTE_CALL_DEVRTC_ACK,E_CAUSE_ACT_CON},// = 22,//远程召唤充电桩时钟结果（应答）
    {E_CMD_UP_VIN_AUTH_DATA,E_CAUSE_ACT},//= 23,//vin码鉴权数据(主动)
    {E_CMD_UP_REMOTE_CALL_DEVPARA_ACK,E_CAUSE_ACT_CON},// = 24,//远程召唤设备参数结果(应答)
    {E_CMD_UP_REMOTE_SETQRCODE_ACK,E_CAUSE_ACT_CON},// = 25,//远程设置二维码结果（应答）
    {E_CMD_UP_REMOTE_CALL_DEVCOSTMODERPARA_ACK,E_CAUSE_ACT_CON},//= 26,//远程召唤充电桩计费模型参数结果（应答）
    {E_CMD_UP_REMOTE_CALL_MEDIAFILE_ACK,E_CAUSE_ACT_CON},// = 27,//远程召唤广告桩媒体文件结果（应答）
    {E_CMD_UP_DOWNLOAD_PLAYONFIG_DATA_ACK,E_CAUSE_ACT_CON},// = 28,//下发播放配置方案下行数据结果（应答）
    {E_CMD_UP_REMOTE_CALL_PALYCONFIG_ACK,E_CAUSE_ACT_CON},//= 29,//远程召唤广告桩播放配置方案结果（应答）
    {E_CMD_UP_REMOTE_CALL_MEDIAPLAY_TOTAL_ACK,E_CAUSE_ACT_CON},// = 30,//远程召唤广告桩媒体文件播放统计结果（应答）
    {E_CMD_UP_ROUTINE_CALL_MEDIAPALY_TOTAL,E_CAUSE_ACT_CON},// = 31,//定期上报广告桩媒体文件播放统计结果（应答）
    {E_CMD_UP_REMOTE_ENABLE_CONTROL_ACK,E_CAUSE_ACT_CON},// = 32,//远程使能控制结果（应答）
    {E_CMD_UP_ALARMINFO,E_CAUSE_ACT},// = 33,//告警/故障信息上行数据（主动）
};

void client_set_test_flag(uint8 state){
}
static uint16 getcmdcot(uint8 cmd)
{
    uint32 i = 0;
    for(i = 0;i<sizeof(upcmdcotbuf)/sizeof(struct t_upcmdcot);i++)
    {
       if(upcmdcotbuf[i].cmd == cmd)
       {
           return upcmdcotbuf[i].cot;
       }
    }
    return 0;
}
//单字节压缩
uint32 setbyte(uint8 byte,uint8 *buf,uint32 pos)
{
    uint32 tmppos = pos;
    *(buf+tmppos) = byte;
    tmppos += 1;
    return tmppos;
}
//半字压缩
uint32 sethalfword(uint16 halfbyte,uint8 *buf,uint32 pos)
{
    uint32 tmppos =  pos;

    *(buf+tmppos) = (uint8)halfbyte;
    tmppos += 1;

    *(buf+tmppos) = (uint8)(halfbyte>>8);
    tmppos += 1;

    return tmppos;
}
//全字压缩
uint32 setword(uint32 word,uint8 *buf,uint32 pos)
{
    uint32 tmppos =  pos;

    *(buf+tmppos) = (uint8)word;
    tmppos += 1;

    *(buf+tmppos) = (uint8)(word>>8);
    tmppos += 1;

    *(buf+tmppos) = (uint8)(word>>16);
    tmppos += 1;

    *(buf+tmppos) = (uint8)(word>>24);
    tmppos += 1;

    return tmppos;
}
//数组压缩
uint32 setarray(uint8 *bufsrc,uint32 len,uint8 *bufdst,uint32 pos)
{
    uint32 i;
    uint32 tmppos = pos;

    for( i = 0;i<len;i++)
    {
        *(bufdst+i+tmppos) = *(bufsrc+len-1-i);
    }
    tmppos += len;
    return tmppos;
}
//单字节解压缩
uint8 getbyte(uint8 *bufsrc,uint8 *byte,uint32 pos)
{
    uint32 tmppos =  pos;

    *byte = *(bufsrc+tmppos);
    tmppos += 1;

    return tmppos;
}
//半字解压缩
uint8 gethalfword(uint8 *bufsrc,uint16 *halfword,uint32 pos)
{
    uint32 tmppos =  pos;

    uint16 tmph = (uint16 )(*(bufsrc+pos+1)<<8);
    uint16 tmpl = (uint16 )(*(bufsrc+pos+0));
    *halfword = tmph | tmpl;

    tmppos += 2;
    return tmppos;
}
//全字解压缩
uint8 getword(uint8 *bufsrc,uint32 *word,uint32 pos)
{
   uint32 tmppos =  pos;

   uint32 word1 = (uint32)(*( bufsrc+pos+3)<<24);
   uint32 word2 = (uint32)(*( bufsrc+pos+2)<<16);
   uint32 word3 = (uint32)(*( bufsrc+pos+1)<<8);
   uint32 word4 = (uint32)(*( bufsrc+pos+0));
   *word = word1 | word2 | word3 | word4 ;

   tmppos +=4;
   return tmppos;
}
//数组解压缩
uint8 getarray(uint8 *bufsrc,uint8 *array,uint32 len,uint32 pos)
{
    uint32 i;
    uint32 tmppos = pos;

    for( i = 0;i<len;i++)
    {
      *(array+i) = *(bufsrc+pos+len-1-i);
    }
    tmppos += len;

    return tmppos;
}

#if 0
//协议数据格式: 头部(1个字节) + 长度域(2个字节) + 控制域(4个字节) + 帧标识(1个字节) + 可变结构限定词(1个字节) + 传送原因(2个字节) + 应用服务数据单元公共地址(2个字节) +数据(n个字节)
static struct t_ac_alarmdesc acalarmdescbuf[] =
{
   {E_NW_ALARM_DOOR,"门禁故障"},
   {E_NW_ALARM_SMOKE,"烟感故障"}, 
   {E_NW_ALARM_LIGHTPRO,"避雷器故障"},  
   {E_NW_ALARM_STOPBUTTON,"急停故障"},  
   {E_NW_ALARM_WATER,"水浸故障"}, 
   {E_NW_ALARM_OBLIQUE,"倾斜故障"},  
   {E_NW_ALARM_FANS,"充电桩风扇故障"}, 
   {E_NW_ALARM_MAINNDEV_FANS,"充电主机风扇故障"},  
   {E_NW_ALARM_PE,"接地故障"}, 
   {E_NW_ALARM_LCD_COMM,"触摸屏通宵故障"}, 
   {E_NW_ALARM_RFCARD,"读卡器通信故障"}, 
   {E_NW_ALARM_PRINT,"打印机通信故障"},
   {E_NW_ALARM_MODULE,"充电模块故障"}, 
   {E_NW_ALARM_MODULE_COMM,"充电模块通信故障"},  
   {E_NW_ALARM_INSULATION,"绝缘检测故障"}, 
   {E_NW_ALARM_ASSIANTPOWER,"辅助电源故障"},  
   {E_NW_ALARM_FULE,"熔断器故障"}, 
   {E_NW_ALARM_PE_BREAK,"PE断线故障"},  
   {E_NW_ALARM_CP_CONNECT,"CP连接故障"}, 
   {E_NW_ALARM_SYS_LOSTPOWER,"系统掉电故障"},  
   {E_NW_ALARM_ELEC_COMM,"电能表通信故障"}, 
   {E_NW_ALARM_ELEC_CAL,"电能表计量故障"}, 
   {E_NW_ALARM_INPIT_BREAKER,"交流输入断路器故障"}, 
   {E_NW_ALARM_OUTPUT_ACTION,"交流输出接触器据动/误动故障"}, 
   {E_NW_ALARM_OUTPUTBREAKER_ADJOIN,"交流输出接触器粘连故障"}, 
   {E_NW_ALARM_LOCK,"充电接口电子锁故障"}, 
   {E_NW_ALARM_NONE_0X1B,"0x1b保留"},  
   {E_NW_ALARM_OVERTEMP ,"充电桩过温故障"}, 
   {E_NW_ALARM_INTERFAVE_OVERTEMP,"充电接口过温故障"},  
   {E_NW_ALARM_V_OVER_A,"交流A相电压过压故障"}, 
   {E_NW_ALARM_V_OVER_B,"交流B相电压过压故障"}, 
   {E_NW_ALARM_V_OVER_C,"交流C相电压过压故障"}, 
   {E_NW_ALARM_V_LOW_A,"交流A相电压欠压故障"}, 
   {E_NW_ALARM_V_LOW_B,"交流B相电压欠压故障"}, 
   {E_NW_ALARM_V_LOW_C,"交流C相电压欠压故障"}, 
   {E_NW_ALARM_I_OVER_A,"交流A相电流过流故障"}, 
   {E_NW_ALARM_I_OVER_B,"交流B相电流过流故障"}, 
   {E_NW_ALARM_I_OVER_C,"交流C相电流过流故障"}, 
   {E_NW_ALARM_DEV_PLAT_COMM,"充电桩与运营平台通信故障"}, 
   {E_NW_ALARM_OTHER,"其他故障"}, 
};
#endif

enum{SQ_TYPE_EQUAL=0X80, SQ_TYPE_NO_EQUAL=0X00};
enum {FRAME_TYPE_I = 0, FRAME_TYPE_S, FRAME_TYPE_U};

struct ST_ConField
{
  uint8 con1;
  uint8 con2;
  uint8 con3;
  uint8 con4;
};

static uint8 GetConField(struct ST_ConField *field,uint8 type)
{

    if (type == FRAME_TYPE_I)
    {
        field->con1 = (_nwpromsg->_sendCnt<<1) & 0xff;
        field->con2 = ((_nwpromsg->_sendCnt<<1)>>8) & 0xff;
        field->con3 = (_nwpromsg->_recvCnt<<1) & 0xff;
        field->con4 = ((_nwpromsg->_recvCnt<<1)>>8) & 0xff;
        _nwpromsg->_sendCnt++;
    }
    else if (type == FRAME_TYPE_S)
    {

    }
    else if (type == FRAME_TYPE_U)
    {

    }
    return 1;
}

static void nw_sm4dec(uint8 *key,uint32 len,uint8 *input,uint32 *output)//sm4解密
{
    sm4_context ctx;

    sm4_setkey_dec(&ctx, key);
    sm4_crypt_ecb(&ctx, 0, len, input, (uint8 *)output);
}
static void nw_sm4enc(uint8 *key,uint32 len, uint8 *input,uint8 *output,uint32 *lenout)//sm4加密
{
    uint8 tmpdata[PRO_MAX_DATA] = {0};

    memset(tmpdata,0,sizeof(tmpdata));
    memcpy(tmpdata,input,len);

    uint32 tmplen = len%16;
    uint32 lastlen = 0;
    if(tmplen != 0)
    {
       lastlen = 16-tmplen;
       tmplen = len + lastlen;
    }
    else
    {
        tmplen = len;
    }

    sm4_context ctx;

    sm4_setkey_enc(&ctx, key);
    sm4_crypt_ecb(&ctx, 1, tmplen, tmpdata, output);

    *lenout = tmplen;
}

struct t_nw_asduhead//应用服务数据单元
{
    struct ST_ConField field;//4个8位数组
    uint8 type;//类型标识
    uint8 vsq;//可变结构限定词
    uint16 cot;//传送原因
    uint16 publicaddr;//应用服务数据单元地址
};
#if 0
//拿取长度
static uint32 getlenth(struct t_pro_recvinfo *recvinfo)
{
    return (recvinfo->tail + recvinfo->head + MAX_PRPRECVDATA_LEN)% MAX_PRPRECVDATA_LEN;
}
#endif

//压进队列
static uint8 push_recvlist(struct t_pro_recvinfo *info,const uint8 *buf,uint32 len)
{
    uint32 i = 0;
    for(i = 0;i<len;i++)
    {
      if(info->head == ((info->tail +1)%MAX_PRPRECVDATA_LEN))//队列已满
      {
         return 0;
      }
      uint32 pos = info->tail;
      *(info->recvlist+pos) = *(buf+i);
      info->tail = (info->tail+1)%MAX_PRPRECVDATA_LEN;
    }
    return 1;
}

//从队列拿出
static uint8 pop_recvlist(struct t_pro_recvinfo *info,uint8 *buf,uint32 *len)
{
    while(1)
    {
        if(info->head == info->tail)//队列为空
        {
           return 0;
        }
        uint8 head = *(info->recvlist+info->head);

        if(head!= _nwpromsg->apcihead)//头部信息不对
        {
          info->head = (info->head +1)%MAX_PRPRECVDATA_LEN;//头部前移
          continue;
        }
        else//头部信息对了
        {
					uint32 pos = 0;
					pos = (info->head+1)%MAX_PRPRECVDATA_LEN;
          uint16 lenl = *(info->recvlist+pos);
					
					pos = (info->head+2)%MAX_PRPRECVDATA_LEN;
					uint16 lenh = *(info->recvlist+pos);
				  lenh = lenh<<8;
					
					uint16 lenread = lenh | lenl;
									
				  pos = 0;
					while(1)
					{						
						 uint32 tmppos = (info->head+3+pos)%MAX_PRPRECVDATA_LEN;
						 *(buf+pos) = *(info->recvlist+tmppos);
						  pos++;
						  if(pos >= lenread)
							{
								break;
							}
					}          
          *len = lenread;
          info->head = (info->head + lenread +3)%MAX_PRPRECVDATA_LEN;//头部前移
          return 1;
        }
    }
}
static uint32  add_head_length(uint8 *data,uint32 length)
{
    uint32  lenout = 0;

    if((length>4) && *(data+0) != 0xff)//需要加密
    {
       uint8 sm4data[PRO_MAX_DATA] = {0};
       memset(sm4data,0,sizeof(sm4data));
       nw_sm4enc(_nwpromsg->sm4,length-10,data+10,sm4data,&lenout);//sm4加密

       memcpy(data+10,sm4data,lenout); //加密之后把加密部分添加到data
       lenout = lenout +10;
    }
    else//不需要加密
    {
      lenout = length;
    }
    uint8 tmpbuf[PRO_MAX_DATA] = {0};
    memset(tmpbuf,0,sizeof(tmpbuf));

    uint32 pos = 0;

    memcpy(tmpbuf,data,lenout);


    pos = setbyte(_nwpromsg->apcihead,data,pos);
    pos = sethalfword(lenout,data,pos);
    memcpy(data+pos,tmpbuf,lenout);

    return lenout+3;
}
#if 0
//信息
static uint16 getsendmsgsn(uint16 *sendmsgsn)
{
    *sendmsgsn = *sendmsgsn + 1;
    if (*sendmsgsn == 0)
    {
        *sendmsgsn = 1;
    }
    return *sendmsgsn;
}

static uint16 getsendcmdsn(uint16 *sendcmdsn)
{
    *sendcmdsn =  *sendcmdsn +1;
    if (*sendcmdsn == 0x8000)
    {
        *sendcmdsn = 1;
    }
    return (*sendcmdsn | 0x8000);
}
#endif
static uint8 GetVSQ(uint8 sq, uint8 num)
{
    return (sq | num);
}

static uint16 getpublicaddr(void)
{
    return _nwpromsg->publicaddr;
}
#if 0
static void send_charge_auth()//E_CMD_UP_CHARGE_AUTH = 1,//鉴权数据
{}
static void send_charge_record()//E_CMD_UP_CHARGE_RECORD = 2, //充电记录上传数据
{}
static void send_getrandom_num()//E_CMD_UP_RANDOM_NUM=3, //交易取随机数
{}
static void send_needto_costmode()//E_CMD_UP_COST_MODE_REQ=4, //请求下发计费模型数据
{}
static void send_needto_costmode_ack()//E_CMD_UP_COST_MODE_ACK=5, //下发计费模型结果数据
{}
static void send_doubleauth_datareq()//E_CMD_UP_DOUBLE_AUTH_DATA_REQ=6, //双向认证终端发起双向认证上行数据
{}
static void send_doubleauth_data()//E_CMD_UP_DOUBLE_AUTH_DATA_UP=7, //双向认证终端上送认证上行数据
{}
static void send_esamkey_normaldata()//E_CMD_UP_ESAM_KEY_NORMAL=8, //ESAM密钥更新中基本数据
{}
static void send_esamkey_file1updata_ack()//E_CMD_UP_ESAM_FIELD1_ACK=9, //ESAM密钥文件1更新成功数据
{}
static void send_esamkey_file2updata_ack()// E_CMD_UP_ESAM_FIELD2_ACK=10, //ESAM密钥文件2更新成功数据
{}
static void send_blacklist_ack()//E_CMD_UP_BLACKLIST = 11,//黑名单下发时上行数据
{}
static void send_doubleauth_data_ack()//E_CMD_UP_DOUBLE_AUTH_DATA_ACK=12, //双向认证终端认证运营管理系统上行数据
{}
static void send_remote_startcharge_ack()//E_CMD_UP_REMOTE_START_CHARGE=13, //远程启动充电执行结果
{}
static void send_remote_stopcharge_ack()//E_CMD_UP_REMOTE_STOP_CHARGE=14, //远程终止充电执行结果
{}
static void send_remote_powerctl_ack()//E_CMD_UP_REMOTE_POWER_SET=15,//远程功率控制结果
{}
static void send_remote_update_ack()//E_CMD_UP_REMOTE_UPDATE=16,//远程升级启动命令接收结果
{}
static void send_charging_recorddata()//E_CMD_UP_CHARGING_DATA=17,//充电过程中上传数据
{}
static void send_devpara_set_ack()//E_CMD_UP_DEV_PARA_SET_ACK=18, //充电设备上报参数设置结果
{}
static void send_sm4_update_ack()//E_CMD_UP_SM4_KEY_UPDATE_ACK=19, //SM4密钥更新结果
{}
static void send_remotecall_chargerecord_ack()//E_CMD_UP_REMOTE_CALL_RECORD_ACK = 20,//远程召唤充电记录结果通知
{}
static void send_remoteupdate_userremain_ack()//E_CMD_UP_REMOTE_UPDATE_USER_REMAIN_ACK = 21,//远程更新用户帐户余额通知
{}
static void send_remotecall_devrtc_ack()//E_CMD_UP_REMOTE_CALL_DEVRTC_ACK = 22,//远程召唤充电桩时钟结果
{}
static void send_vin_authdata()//E_CMD_UP_VIN_AUTH_DATA = 23,//vin码鉴权数据
{}
static void send_remotecall_devpara_ack()//E_CMD_UP_REMOTE_CALL_DEVPARA_ACK = 24,//远程召唤设备参数结果
{}
static void send_remote_setercode_ack()//E_CMD_UP_REMOTE_SETQRCODE_ACK = 25,//远程设置二维码结果
{}
static void send_remotecall_devcostmode_ack()//E_CMD_UP_REMOTE_CALL_DEVCOSTMODERPARA_ACK= 26,//远程召唤充电桩计费模型参数结果
{}
static void send_remotecall_mediafile_ack()//E_CMD_UP_REMOTE_CALL_MEDIAFILE_ACK = 27,//远程召唤广告桩媒体文件结果
{}
static void send_boardup_configdata_ack()//E_CMD_UP_DOWNLOAD_PLAYONFIG_DATA_ACK = 28,//下发播放配置方案下行数据结果
{}
static void	send_remotecall_boardup_config_ack()//E_CMD_UP_REMOTE_CALL_PALYCONFIG_ACK= 29,//远程召唤广告桩播放配置方案结果
{}
static void	send_remotecall_mediaboardup_cnt_ack()// E_CMD_UP_REMOTE_CALL_MEDIAPLAY_TOTAL_ACK = 30,//远程召唤广告桩媒体文件播放统计结果
{}
static void	send_remotecall_ontimereport_mediaboardup_cnt_ack()//E_CMD_UP_ROUTINE_CALL_MEDIAPALY_TOTAL = 31,//定期上报广告桩媒体文件播放统计结果
{}
static void	send_remote_enablectr_ack()//E_CMD_UP_REMOTE_ENABLE_CONTROL_ACK = 32,//远程使能控制结果
{}
static void	send_alarm_msg()//E_CMD_UP_ALARMINFO = 33,//告警/故障信息上行数据  
{} 
#endif
void nwpro_init(struct t_nw_promsg *msg)//协议模块初始化
{
	 _nwpromsg = msg;
}
void nwpro_pushrecvdata(uint8 *data,uint32 len)//接收数据
{
   push_recvlist(&_nwpromsg->recvinfo,data,len);
}
uint8 nwpro_getrecvdata(uint8 *cmdget,uint8 *dataget,uint32 *lenget)
{
   uint8 tmpdata[500] = {0};
   uint32 tmplen = 0;

   uint8 ret = pop_recvlist(&_nwpromsg->recvinfo,tmpdata,&tmplen);//拿取的数据:控制域(4个字节) + 帧标识(1个字节) + 可变结构限定词(1个字节) + 传送原因(2个字节) + 应用服务数据单元公共地址(2个字节) +数据(n个字节)
   if(!ret)
   {
     return 0;
   }

   uint8 con1 = 0;
   uint32 pos = 0;

   pos = getbyte(tmpdata,&con1,pos);

   if (con1 == 0xff)//协议标志帧
   {
       *cmdget = E_TYPE_SIGN_IN_ACK;
       return 1;
   }
   else if ((con1 & 0x01) == 0)//I帧 带数据帧
   {
       uint8 sm4buf[PRO_MAX_DATA] = {0};

       uint32 lensm4 = tmplen-4-6;//sm4解密的长度 = 解析到的长度减去 4个字节的控制域 + 6个字节包信息
       uint8 *sm4data = tmpdata+4+6;//...
       nw_sm4dec(_nwpromsg->sm4,lensm4,sm4data,(uint32 *)sm4buf);

       //解析完成后重新加回到原信息里面去
        memcpy(tmpdata+10,sm4buf,lensm4);
       *cmdget = *(tmpdata+4);
       *lenget =  tmplen-4;
       memcpy(dataget,tmpdata+4,*lenget);
       return 1;
   }
   else if ((con1 & 0x03) == 1)//S帧 应答帧 不带数据
   {

   }
   else if ((con1 & 0x03) == 3)//U帧 控制帧 不带数据
   {
     if (con1 == 0x83)
     {
        *cmdget = E_TYPE_LIVE_MSG_ACK;
        return 1;
     }
     else if (con1 == 0x07)
     {
        *cmdget = E_TYPE_STARTDT_REQ;
        return 1;
     }
     else if (con1 == 0x13)
     {
        *cmdget = E_TYPE_STOPDT_REQ;
        return 1;
     }
   }
   return 0;
}
uint16 getcot(uint8 *data,uint32 len)
{
    uint16 cot = 0;
    uint32 pos = 2;

    pos = gethalfword(data,&cot,pos);//传送原因

    return cot;

}
void pro_gettime(uint8 *data,uint8 *time)
{
    struct t_nw_asduhead asduhead;
    uint8 objaddr[OBJADDR_LEN] = {0};

    memset((uint8 *)&asduhead,0,sizeof(asduhead));
    memset(objaddr,0,sizeof(objaddr));

    uint32 pos = 0;

    pos = getbyte(data,&asduhead.type,pos);
    pos = getbyte(data,&asduhead.vsq,pos);
    pos = gethalfword(data,&asduhead.cot,pos);
    pos = gethalfword(data,&asduhead.publicaddr,pos);
    pos = getarray(data,objaddr,OBJADDR_LEN,pos);

   pos = getarray(data,time,7,pos);
}
void pro_dealkeepliveack(void)//处理心跳包
{
    _nwpromsg->_sendCnt = 0;
}
uint8 nw_getprocmd(uint8 *data,const uint32 len,uint8 *dataget,uint32 *lenget)//获取下发数据项命令与数据
{
    struct t_nw_asduhead asduhead;
    uint8 objaddr[OBJADDR_LEN] = {0};

    memset((uint8 *)&asduhead,0,sizeof(asduhead));
    memset(objaddr,0,sizeof(objaddr));

    uint32 pos = 0;

    pos = getbyte(data,&asduhead.type,pos);
    pos = getbyte(data,&asduhead.vsq,pos);
    pos = gethalfword(data,&asduhead.cot,pos);
    pos = gethalfword(data,&asduhead.publicaddr,pos);
    pos = getarray(data,objaddr,OBJADDR_LEN,pos);

    uint8 cmd = 0;
    pos = getbyte(data,&cmd,pos);

    *lenget = len - pos;
    memcpy(dataget,data+pos,*lenget);

    return cmd;
}
void pro_getcmd_reportparaset(uint8 *data,uint32 len,void *msg)
{
    struct t_down_reportpara_set *pstr = (struct t_down_reportpara_set *)msg;

    uint32 pos = 0;
    pos = getarray(data, pstr->devnum,8,pos);
    pos = getbyte(data,&pstr->gunno,pos);
    pos = gethalfword(data,&pstr->interval_datarep,pos);
    pos = gethalfword(data,&pstr->interval_minrep,pos);
    pos = gethalfword(data,&pstr->interval_keeplive,pos);
    pos = getarray(data,pstr->ip,4,pos);;
    pos = gethalfword (data,&pstr->port,pos);
}
void pro_getcmd_costmode(uint8 *data,uint32 len,void *msg)//处理计费模型下发
{
    struct t_down_costmode *pstr  = ( struct t_down_costmode *)msg;
    uint32 pos = 0;

    pos = getarray(data,pstr->devnum,8,pos);
    pos = getbyte(data,&pstr->gunno,pos);
    pos = getarray(data,pstr->costmode_id,8,pos);
    pos = getarray(data,pstr->begintime,7,pos);
    pos = getarray(data,pstr->endtime,7,pos);
    pos = gethalfword(data,&pstr->state,pos);
    pos = gethalfword(data,&pstr->caltype,pos);
    pos = getbyte(data,&pstr->timenum,pos);
}
void pro_getcmd_costmodedata(uint8 *data,uint32 len,struct t_costmodemsg *msg,uint32 cnt)//获取计费模型数据
{
    uint32 pos = 0;
    pos += 36;

    uint32 i = 0;
    for(;i<cnt;i++)
    {
        pos = gethalfword(data,&(msg+i)->begintime,pos);
        pos = getbyte(data,&(msg+i)->flag,pos);
        pos = getword(data,&(msg+i)->elec_tip,pos);
        pos = getword(data,&(msg+i)->elec_peak,pos);
        pos = getword(data,&(msg+i)->elec_normal,pos);
        pos = getword(data,&(msg+i)->elec_valley,pos);
        pos = getword(data,&(msg+i)->pcs_server,pos);
        pos = getword(data,&(msg+i)->pcs_position,pos);
        pos = getword(data,&(msg+i)->pcs_reserve,pos);
    }
}
void pro_getcmd_remotestart(uint8 *data,uint32 len,struct t_down_remote_start *msg)
{
	  uint32 pos = 0; 
	  pos = getarray(data,msg->devnum,8,pos);
	  pos = getbyte(data,&msg->gunno,pos);
	  pos = getword(data,&msg->remain,pos);
	
	  pos = getarray(data,msg->userid,8,pos);
	  pos = getbyte(data,&msg->type,pos);
	
	  uint8 value[3] = {0};
		uint8 tmpvalue[10] = {0};
	  pos = getarray(data,value,3,pos);
    BCD_to_ASC(tmpvalue,value,3);
		msg->value = atoi((char *)tmpvalue);
		
	  pos = getarray(data,msg->orderno,8,pos);	
}
void pro_getcmd_remotestop(uint8 *data,uint32 len,struct t_down_remote_stop *msg)
{
	  uint32 pos = 0; 
	  pos = getarray(data,msg->devnum,8,pos);
	  pos = getbyte(data,&msg->gunno,pos);
	  pos = getarray(data,msg->stop,8,pos);
}
void pro_getcmd_chargingrecord(uint8 *data,uint32 len,struct t_down_chargingrecord_ack *ack)//上传充电记录应答
{
	  uint32 pos = 0; 
	  pos = getarray(data,ack->devnum,8,pos);
	  pos = getbyte(data,&ack->gunno,pos);
	  pos = getbyte(data,&ack->flag,pos);
	  pos = getarray(data,ack->trade_serialnum,16,pos);
}
void pro_getcmd_cardauth(uint8 *data,uint32 len,struct t_down_authdata *ack)//充电鉴权应答数据
{
	uint32 pos = 0;
	pos = getarray(data,ack->devnum,8,pos);
	pos = getbyte(data,&ack->gunno,pos);
	pos = getarray(data,ack->cardno,8,pos);
	pos = getarray(data,ack->carvin,32,pos);
	pos = getarray(data,ack->costmodenum,8,pos);
	pos = getword(data,&ack->reamin_money,pos);
	pos = getbyte(data,&ack->authflag,pos);
	pos = gethalfword(data,&ack->auth_failreason,pos);
	pos = getword(data,&ack->remain_km,pos);
	pos = getword(data,&ack->avalib_power,pos);
	pos = getword(data,&ack->avalib_cnt,pos);
	pos = getarray(data,ack->orderno,8,pos);

}
void pro_getcmd_remoteupdate(uint8 *data,uint32 len,struct t_down_remote_updatestart *updatedata)//远程启动升级
{
	uint32 pos = 0;
  pos = getarray(data,updatedata->devnum,8,pos);
	pos = getbyte(data,&updatedata->flag,pos);
	pos = getarray(data,updatedata->ip,4,pos);//远端升级ip 
	pos = getbyte(data,&updatedata->port,pos);//端口号
	pos = getarray(data,updatedata->ftp_user,10,pos);//用户名
	pos = getarray(data,updatedata->ftp_password,10,pos);//密码
	pos = getarray(data,updatedata->pwd,50,pos);//路径
	pos = getarray(data,updatedata->filename,50,pos);//文件名
	pos = getarray(data,updatedata->fac_num,10,pos);//厂家编码
	pos = getarray(data,updatedata->hardware_ver,30,pos);//硬件版本号
	pos = getarray(data,updatedata->software_ver,20,pos);//软件版本号
}
void probill_proinitmsg(struct t_nw_pro_init *msg,uint8 *data,uint32 *len)//协议部分构建协议标识帧
{
  uint32 pos = 0;

  pos = setbyte(msg->flag,data,pos);
  pos = setbyte(msg->ver,data,pos);
  pos = setarray(msg->costmode_id,8,data,pos);
  pos = setarray(msg->devnum,8,data,pos);
  pos = setbyte(msg->gun_cnt,data,pos);
  pos = setbyte(msg->chargemode,data,pos);
  pos = sethalfword(msg->addr,data,pos);

  pos = add_head_length(data,pos);

  *len = pos;
}

void probill_startdtmsg(uint8 *data,uint32 *len)
{

  uint8 ctrl[4] = {0};
  ctrl[0] = 0x0b;

  uint32 pos = 0;

  pos = setbyte(ctrl[0],data,pos);
  pos = setbyte(ctrl[1],data,pos);
  pos = setbyte(ctrl[2],data,pos);
  pos = setbyte(ctrl[3],data,pos);

  pos = add_head_length(data,pos);

  *len = pos;
}
void probill_allcall(uint16 cot,uint8 *data,uint32 *len)//协议部分构建类型100的数据
{

    struct t_nw_asduhead asduhead;
    uint8 objaddr[OBJADDR_LEN] = {0};
    uint8 QOI = 0;

    memset((uint8 *)&asduhead,0,sizeof(asduhead));
    memset(objaddr,0,sizeof(objaddr));

    GetConField(&asduhead.field,FRAME_TYPE_I);
    asduhead.type = E_TYPE_C_IC_NA_1;//类型标识
    asduhead.vsq = GetVSQ(SQ_TYPE_EQUAL,1);//可变结构限定词
    asduhead.cot = cot;//传送原因
    asduhead.publicaddr = getpublicaddr();//应用服务数据单元地址

    uint32 pos = 0;

    pos = setbyte( asduhead.field.con1,data,pos);
    pos = setbyte( asduhead.field.con2,data,pos);
    pos = setbyte( asduhead.field.con3,data,pos);
    pos = setbyte( asduhead.field.con4,data,pos);

    pos = setbyte(asduhead.type,data,pos);
    pos = setbyte(asduhead.vsq,data,pos);
    pos = sethalfword(asduhead.cot,data,pos);
    pos = sethalfword(asduhead.publicaddr,data,pos);
    pos = setarray(objaddr,sizeof(objaddr),data,pos);
    pos = setbyte(QOI,data,pos);

    pos = add_head_length(data,pos);

    *len = pos;
}
void probill_acyx(uint16 cot,uint32 gunno,struct t_ac_devyx *yxdata,uint8 *data,uint32 *len)
{
    struct t_nw_asduhead asduhead;
    uint8 objaddr[OBJADDR_LEN] = {0};

    memset((uint8 *)&asduhead,0,sizeof(asduhead));
    memset(objaddr,0,sizeof(objaddr));

    GetConField(&asduhead.field,FRAME_TYPE_I);
    asduhead.type = E_TYPE_M_SP_NA_1;
    asduhead.vsq = GetVSQ(SQ_TYPE_EQUAL, sizeof(struct t_ac_devyx));//第二个参数要根据实际单点数据个数做修改
    asduhead.cot = cot;
    asduhead.publicaddr = getpublicaddr();

    uint32 pos = 0;

    pos = setbyte( asduhead.field.con1,data,pos);
    pos = setbyte( asduhead.field.con2,data,pos);
    pos = setbyte( asduhead.field.con3,data,pos);
    pos = setbyte( asduhead.field.con4,data,pos);

    pos = setbyte(asduhead.type,data,pos);
    pos = setbyte(asduhead.vsq,data,pos);
    pos = sethalfword(asduhead.cot,data,pos);
    pos = sethalfword(asduhead.publicaddr,data,pos);

    pos = setarray(objaddr,sizeof(objaddr),data,pos);

    pos =  setbyte(yxdata->connect_state,data,pos);
    pos =  setbyte(yxdata->ac_input_v_overalarm,data,pos);
    pos =  setbyte(yxdata->ac_input_v_lowlarm,data,pos);
    pos =  setbyte(yxdata->current_overalarm,data,pos);
    pos =  setbyte(yxdata->output_relay_state,data,pos);
    pos =  setbyte(yxdata->temp_over_pro,data,pos);
    pos =  setbyte(yxdata->short_circuit_pro,data,pos);
    pos =  setbyte(yxdata->leakage_pro,data,pos);
    pos =  setbyte(yxdata->stopbutton_trigger,data,pos);

    pos = add_head_length(data,pos);

    *len = pos;
}
void probill_acyc_halfword(uint16 cot,uint32 gunno,struct t_ac_devyc_halfword *ycdata,uint8 *data,uint32 *len)
{
    struct t_nw_asduhead asduhead;
    uint8 objaddr[OBJADDR_LEN] = {0};

    memset((uint8 *)&asduhead,0,sizeof(asduhead));
    memset(objaddr,0,sizeof(objaddr));

    GetConField(&asduhead.field,FRAME_TYPE_I);
    asduhead.type = E_TYPE_M_ME_NB_1;
    asduhead.vsq = GetVSQ(SQ_TYPE_EQUAL,sizeof(struct t_ac_devyc_halfword)/2);//第二个参数要根据实际单点数据个数做修改
    asduhead.cot = cot;
    asduhead.publicaddr = getpublicaddr();

    uint8 qds = 0;
    uint32 pos = 0;

    pos = setbyte(asduhead.field.con1,data,pos);
    pos = setbyte(asduhead.field.con2,data,pos);
    pos = setbyte(asduhead.field.con3,data,pos);
    pos = setbyte(asduhead.field.con4,data,pos);

    pos = setbyte(asduhead.type,data,pos);
    pos = setbyte(asduhead.vsq,data,pos);
    pos = sethalfword(asduhead.cot,data,pos);
    pos = sethalfword(asduhead.publicaddr,data,pos);

    pos = setarray(objaddr,sizeof(objaddr),data,pos);

    pos = sethalfword(ycdata->work_state,data,pos);
    pos = setbyte(qds,data,pos);

    pos = sethalfword(ycdata->output_voltage,data,pos);
    pos = setbyte(qds,data,pos);

    pos = sethalfword(ycdata->output_current,data,pos);
    pos = setbyte(qds,data,pos);

    pos = sethalfword(ycdata->voltage_A,data,pos);
    pos = setbyte(qds,data,pos);

    pos = sethalfword(ycdata->voltage_B,data,pos);
    pos = setbyte(qds,data,pos);

    pos = sethalfword(ycdata->voltage_C,data,pos);
    pos = setbyte(qds,data,pos);

    pos = sethalfword(ycdata->current_A,data,pos);
    pos = setbyte(qds,data,pos);

    pos = sethalfword(ycdata->current_B,data,pos);
    pos = setbyte(qds,data,pos);

    pos = sethalfword(ycdata->currenr_C,data,pos);
    pos = setbyte(qds,data,pos);

    pos = add_head_length(data,pos);

    *len = pos;

}
void probill_acyc_morehalfword(uint16 cot,uint32 gunno,struct t_ac_devyc_morehalfword *ycdata,uint8 *data,uint32 *len)
{
    struct t_nw_asduhead asduhead;
    uint8 objaddr[OBJADDR_LEN] = {0};

    memset((uint8 *)&asduhead,0,sizeof(asduhead));
    memset(objaddr,0,sizeof(objaddr));

    GetConField(&asduhead.field,FRAME_TYPE_I);
    asduhead.type = E_TYPE_M_MD_NA_1;
    asduhead.vsq = GetVSQ(SQ_TYPE_EQUAL, sizeof(struct t_ac_devyc_morehalfword)/4);//第二个参数要根据实际单点数据个数做修改
    asduhead.cot = cot;
    asduhead.publicaddr = getpublicaddr();

    uint8 valuelen = 4;
    uint8 value = 0;

    uint32 pos = 0;

    pos = setbyte( asduhead.field.con1,data,pos);
    pos = setbyte( asduhead.field.con2,data,pos);
    pos = setbyte( asduhead.field.con3,data,pos);
    pos = setbyte( asduhead.field.con4,data,pos);

    pos = setbyte(asduhead.type,data,pos);
    pos = setbyte(asduhead.vsq,data,pos);
    pos = sethalfword(asduhead.cot,data,pos);
    pos = sethalfword(asduhead.publicaddr,data,pos);

    pos = setarray(objaddr,sizeof(objaddr),data,pos);

    pos = setbyte(valuelen,data,pos);
    pos = setword(ycdata->total_actually_power,data,pos);
    pos = setbyte(value,data,pos);

    pos = setbyte(valuelen,data,pos);
    pos = setword(ycdata->elecvalue_outside,data,pos);
    pos = setbyte(value,data,pos);

    pos = add_head_length(data,pos);

    *len = pos;
}
void probill_timesync_ack(uint16 cot,uint8 *time,uint8 *data,uint32 *len)
{
    struct t_nw_asduhead asduhead;
    memset((uint8 *)&asduhead,0,sizeof(asduhead));

    uint8 objaddr[OBJADDR_LEN] = {0};
    memset(objaddr,0,sizeof(objaddr));

    uint32 pos = 0;

    GetConField(&asduhead.field,FRAME_TYPE_I);
    asduhead.type = E_TYPE_C_CS_NA_1;
    asduhead.vsq = GetVSQ(SQ_TYPE_EQUAL, 1);//第二个参数要根据实际单点数据个数做修改
    asduhead.cot = cot;
    asduhead.publicaddr = getpublicaddr();

    pos = setbyte( asduhead.field.con1,data,pos);
    pos = setbyte( asduhead.field.con2,data,pos);
    pos = setbyte( asduhead.field.con3,data,pos);
    pos = setbyte( asduhead.field.con4,data,pos);

    pos = setbyte(asduhead.type,data,pos);
    pos = setbyte(asduhead.vsq,data,pos);
    pos = sethalfword(asduhead.cot,data,pos);
    pos = sethalfword(asduhead.publicaddr,data,pos);

    pos = setarray(objaddr,sizeof(objaddr),data,pos);

    pos = setarray(time,7,data,pos);

    pos = add_head_length(data,pos);

    *len = pos;
}

void probill_devparaset_ack(const struct t_up_reportpara_set_ack *ack,uint8 *data,uint32 *len)//设备参数设置应答
{
    uint8 CMD = E_CMD_UP_DEV_PARA_SET_ACK;
    struct t_nw_asduhead asduhead;
    memset((uint8 *)&asduhead,0,sizeof(asduhead));

    uint8 objaddr[OBJADDR_LEN] = {0};
    memset(objaddr,0,sizeof(objaddr));

    uint32 pos = 0;

    GetConField(&asduhead.field,FRAME_TYPE_I);
    asduhead.type = E_TYPE_M_RE_NA_1;
    asduhead.vsq = GetVSQ(SQ_TYPE_NO_EQUAL, 1);//第二个参数要根据实际单点数据个数做修改
    asduhead.cot = getcmdcot(CMD);
    asduhead.publicaddr = getpublicaddr();

    pos = setbyte( asduhead.field.con1,data,pos);
    pos = setbyte( asduhead.field.con2,data,pos);
    pos = setbyte( asduhead.field.con3,data,pos);
    pos = setbyte( asduhead.field.con4,data,pos);

    pos = setbyte(asduhead.type,data,pos);
    pos = setbyte(asduhead.vsq,data,pos);
    pos = sethalfword(asduhead.cot,data,pos);
    pos = sethalfword(asduhead.publicaddr,data,pos);

    pos = setarray(objaddr,sizeof(objaddr),data,pos);

    pos = setbyte(CMD,data,pos);
    pos = setarray((uint8 *)ack->devnum,8,data,pos);
    pos = setbyte(ack->gunno,data,pos);
    pos = setbyte(ack->flag,data,pos);

    pos = add_head_length(data,pos);

    *len = pos;
}
void probill_costmode_req(const struct t_up_require_costmode *ack,uint8 *data,uint32 *len)//请求下发计费模型
{
    uint8 CMD = E_CMD_UP_COST_MODE_REQ;
    struct t_nw_asduhead asduhead;
    memset((uint8 *)&asduhead,0,sizeof(asduhead));

    uint8 objaddr[OBJADDR_LEN] = {0};
    memset(objaddr,0,sizeof(objaddr));

    uint32 pos = 0;

    GetConField(&asduhead.field,FRAME_TYPE_I);
    asduhead.type = E_TYPE_M_RE_NA_1;
    asduhead.vsq = GetVSQ(SQ_TYPE_NO_EQUAL, 1);//第二个参数要根据实际单点数据个数做修改
    asduhead.cot = getcmdcot(CMD);
    asduhead.publicaddr = getpublicaddr();

    pos = setbyte( asduhead.field.con1,data,pos);
    pos = setbyte( asduhead.field.con2,data,pos);
    pos = setbyte( asduhead.field.con3,data,pos);
    pos = setbyte( asduhead.field.con4,data,pos);

    pos = setbyte(asduhead.type,data,pos);
    pos = setbyte(asduhead.vsq,data,pos);
    pos = sethalfword(asduhead.cot,data,pos);
    pos = sethalfword(asduhead.publicaddr,data,pos);

    pos = setarray(objaddr,sizeof(objaddr),data,pos);

    pos = setbyte(CMD,data,pos);
    pos = setarray((uint8 *)ack->devnum,8,data,pos);
    pos = setbyte(ack->gunno,data,pos);

    pos = add_head_length(data,pos);

    *len = pos;
}

void probill_costmode_ack(const struct t_up_costmode_ack *ack,uint8 *data,uint32 *len)//下发计费模型应答
{
    uint8 CMD = E_CMD_UP_COST_MODE_ACK;
    struct t_nw_asduhead asduhead;
    memset((uint8 *)&asduhead,0,sizeof(asduhead));

    uint8 objaddr[OBJADDR_LEN] = {0};
    memset(objaddr,0,sizeof(objaddr));

    uint32 pos = 0;

    GetConField(&asduhead.field,FRAME_TYPE_I);
    asduhead.type = E_TYPE_M_RE_NA_1;
    asduhead.vsq = GetVSQ(SQ_TYPE_NO_EQUAL, 1);//第二个参数要根据实际单点数据个数做修改
    asduhead.cot = getcmdcot(CMD);
    asduhead.publicaddr = getpublicaddr();

    pos = setbyte(asduhead.field.con1,data,pos);
    pos = setbyte(asduhead.field.con2,data,pos);
    pos = setbyte(asduhead.field.con3,data,pos);
    pos = setbyte(asduhead.field.con4,data,pos);

    pos = setbyte(asduhead.type,data,pos);
    pos = setbyte(asduhead.vsq,data,pos);
    pos = sethalfword(asduhead.cot,data,pos);
    pos = sethalfword(asduhead.publicaddr,data,pos);

    pos = setarray(objaddr,sizeof(objaddr),data,pos);

    pos = setbyte(CMD,data,pos);
    pos = setarray((uint8 *)ack->devnum,8,data,pos);
    pos = setbyte(ack->gunno,data,pos);
    pos = setarray((uint8 *)ack->costmode_id,8,data,pos);
    pos = setbyte(ack->flag,data,pos);

    pos = add_head_length(data,pos);

    *len = pos;
}
void probill_keeplive_ack(uint8 *data,uint32 *len)//构建心跳包
{
    uint32 pos = 0;
    uint32 con = 0x43;

    pos = setword(con,data,pos);
    pos = add_head_length(data,pos);

    *len = pos;
}
void probill_chargingdata(const struct t_up_chargingdata *chargingdata,uint8 *data,uint32 *len)//上报充电桩运行中数据
{
    uint8 CMD = E_CMD_UP_CHARGING_DATA;
    struct t_nw_asduhead asduhead;
    memset((uint8 *)&asduhead,0,sizeof(asduhead));

    uint8 objaddr[OBJADDR_LEN] = {0};
    memset(objaddr,0,sizeof(objaddr));

    uint32 pos = 0;

    GetConField(&asduhead.field,FRAME_TYPE_I);
    asduhead.type = E_TYPE_M_RE_NA_1;
    asduhead.vsq = GetVSQ(SQ_TYPE_NO_EQUAL, 1);//第二个参数要根据实际单点数据个数做修改
    asduhead.cot = getcmdcot(CMD);
    asduhead.publicaddr = getpublicaddr();

    pos = setbyte(asduhead.field.con1,data,pos);
    pos = setbyte(asduhead.field.con2,data,pos);
    pos = setbyte(asduhead.field.con3,data,pos);
    pos = setbyte(asduhead.field.con4,data,pos);

    pos = setbyte(asduhead.type,data,pos);
    pos = setbyte(asduhead.vsq,data,pos);
    pos = sethalfword(asduhead.cot,data,pos);
    pos = sethalfword(asduhead.publicaddr,data,pos);

    pos = setarray(objaddr,sizeof(objaddr),data,pos);

    pos = setbyte(CMD,data,pos);
    pos = setarray((uint8 *)chargingdata->devnum,8,data,pos);
    pos = setbyte(chargingdata->gunno,data,pos);
    pos = setarray((uint8 *)chargingdata->trade_num,16,data,pos);
    pos = sethalfword(chargingdata->business_type,data,pos);
    pos = setarray((uint8 *)chargingdata->user_id,8,data,pos);
    pos = setarray((uint8 *)chargingdata->cardno,8,data,pos);
    pos = setarray((uint8 *)chargingdata->begintime,7,data,pos);
    pos = setarray((uint8 *)chargingdata->endtime,7,data,pos);
    pos = setword(chargingdata->tip_begin,data,pos);
    pos = setword(chargingdata->tip_end,data,pos);
    pos = setword(chargingdata->peak_begin,data,pos);
    pos = setword(chargingdata->peak_end,data,pos);
    pos = setword(chargingdata->normal_begin,data,pos);
    pos = setword(chargingdata->normal_end,data,pos);
    pos = setword(chargingdata->valley_begin,data,pos);
    pos = setword(chargingdata->valley_end,data,pos);
    pos = setword(chargingdata->tip_power,data,pos);
    pos = setword(chargingdata->peak_power,data,pos);
    pos = setword(chargingdata->normal_power,data,pos);
    pos = setword(chargingdata->valley_power,data,pos);
    pos = setword(chargingdata->total_power,data,pos);
    pos = setword(chargingdata->tip_eleccost,data,pos);
    pos = setword(chargingdata->peak_eleccost,data,pos);
    pos = setword(chargingdata->normal_eleccost,data,pos);
    pos = setword(chargingdata->valley_eleccost,data,pos);
    pos = setword(chargingdata->total_eleccost,data,pos);
    pos = setword(chargingdata->total_servercost,data,pos);
    pos = setword(chargingdata->total_positioncost,data,pos);
    pos = sethalfword(chargingdata->cal_type,data,pos);
    pos = setword(chargingdata->total_begin,data,pos);
    pos = setword(chargingdata->total_end,data,pos);
    pos = setbyte(chargingdata->timesharing_flag,data,pos);
    pos = setarray((uint8 *)chargingdata->vin,17,data,pos);
    pos = sethalfword(chargingdata->total_time,data,pos);
    pos = sethalfword(chargingdata->remain_time,data,pos);
    pos = setword(chargingdata->total_cost,data,pos);
    pos = setarray((uint8 *)chargingdata->orderno,8,data,pos);

    pos = add_head_length(data,pos);

    *len = pos;
}
void probill_chargerecord(const struct t_up_chargerecord *chargerecord,uint8 *data,uint32 *len)//上报充电记录
{
	 uint8 CMD = E_CMD_UP_CHARGE_RECORD;
   struct t_nw_asduhead asduhead;
   memset((uint8 *)&asduhead,0,sizeof(asduhead));

   uint8 objaddr[OBJADDR_LEN] = {0};
   memset(objaddr,0,sizeof(objaddr));

   uint32 pos = 0;

   GetConField(&asduhead.field,FRAME_TYPE_I);
   asduhead.type = E_TYPE_M_RE_NA_1;
   asduhead.vsq = GetVSQ(SQ_TYPE_NO_EQUAL, 1);//第二个参数要根据实际单点数据个数做修改
   asduhead.cot = getcmdcot(CMD);
   asduhead.publicaddr = getpublicaddr();

   pos = setbyte(asduhead.field.con1,data,pos);
   pos = setbyte(asduhead.field.con2,data,pos);
   pos = setbyte(asduhead.field.con3,data,pos);
   pos = setbyte(asduhead.field.con4,data,pos);

   pos = setbyte(asduhead.type,data,pos);
   pos = setbyte(asduhead.vsq,data,pos);
   pos = sethalfword(asduhead.cot,data,pos);
   pos = sethalfword(asduhead.publicaddr,data,pos);

   pos = setarray(objaddr,sizeof(objaddr),data,pos);

   pos = setbyte(CMD,data,pos);
		
	 pos = setarray((uint8 *)chargerecord->devnum,8,data,pos);
	 pos = setbyte(chargerecord->gunno,data,pos);
	 pos = setarray((uint8 *)chargerecord->trade_num,16,data,pos);
	 pos = setarray((uint8 *)chargerecord->paycardno,8,data,pos);
	 
	 pos = setarray((uint8 *)chargerecord->hardcardno,8,data,pos);
	 pos = setbyte(chargerecord->time_sharing_cal_flag,data,pos);
	 pos = setarray((uint8 *)chargerecord->begintime,7,data,pos);
	 pos = setarray((uint8 *)chargerecord->endtime,7,data,pos);
	 pos = setword(chargerecord->tip_start_value,data,pos);
	 pos = setword(chargerecord->tip_stop_value,data,pos);
	 pos = setword(chargerecord->peak_start_value,data,pos);
	 pos = setword(chargerecord->peak_stop_value,data,pos);
	 pos = setword(chargerecord->normal_start_value,data,pos);
	 pos = setword(chargerecord->normal_stop_value,data,pos);
	 pos = setword(chargerecord->valley_start_value,data,pos);
	 pos = setword(chargerecord->valley_stop_value,data,pos);
	 pos = sethalfword(chargerecord->caltype,data,pos);
	 pos = setword(chargerecord->total_start_value,data,pos);
	 pos = setword(chargerecord->total_stop_value,data,pos);
   pos = setword(chargerecord->tip_pcs,data,pos);
	 pos = setword(chargerecord->tip_power,data,pos);
	 pos = setword(chargerecord->tip_money,data,pos);
	 pos = setword(chargerecord->peak_pcs,data,pos);
	 pos = setword(chargerecord->peak_power,data,pos);
	 pos = setword(chargerecord->peak_money,data,pos);
	 pos = setword(chargerecord->normal_pcs,data,pos);
	 pos = setword(chargerecord->normal_power,data,pos);
	 pos = setword(chargerecord->normal_money,data,pos);
	 pos = setword(chargerecord->valley_pcs,data,pos);
	 pos = setword(chargerecord->valley_power,data,pos);
	 pos = setword(chargerecord->valley_money,data,pos);
	 pos = setword(chargerecord->total_power,data,pos);
	 pos = sethalfword(chargerecord->business_type,data,pos);
	 pos = setword(chargerecord->money_afterpay,data,pos);
	 pos = setword(chargerecord->consume_pcs,data,pos);
	 pos = setword(chargerecord->consume_money,data,pos);
	 pos = setarray((uint8 *)chargerecord->carvin,17,data,pos);
	 pos = setbyte(chargerecord->trade_flag,data,pos);
	 pos = setarray((uint8 *)chargerecord->client_terminal_num,6,data,pos);
	 pos = setword(chargerecord->money_beforepay,data,pos);
	 pos = sethalfword(chargerecord->wallet_trade_serialnum,data,pos);
	 pos = setword(chargerecord->trade_money,data,pos);
	 pos = setarray((uint8 *)chargerecord->trade_date,7,data,pos);
	 pos = setword(chargerecord->fake_num,data,pos);
	 pos = setbyte(chargerecord->trade_type_flag,data,pos);
	 pos = setword(chargerecord->tac,data,pos);
	 pos = setbyte(chargerecord->key_ver,data,pos);
	 pos = setword(chargerecord->terminal_trade_serialnum,data,pos);
	 pos = setword(chargerecord->server_pcs,data,pos);
	 pos = setword(chargerecord->server_cost,data,pos);
	 pos = setword(chargerecord->reserve_pcs,data,pos);
	 pos = setword(chargerecord->reserve_cost,data,pos);
   pos = setword(chargerecord->position_pcs,data,pos);
	 pos = setword(chargerecord->position_cost,data,pos);
	 pos = setword(chargerecord->total_eleccost,data,pos);
	 pos = setarray((uint8 *)chargerecord->costmodeid,8,data,pos);
	 pos = setword(chargerecord->total_cost,data,pos);
	 pos = sethalfword(chargerecord->endreason,data,pos);
	 pos = setarray((uint8 *)chargerecord->userid,8,data,pos);
	 pos = setword(chargerecord->tip_server_pcs,data,pos);
	 pos = setword(chargerecord->tip_server_cost,data,pos);
	 pos = setword(chargerecord->peak_server_pcs,data,pos);
	 pos = setword(chargerecord->peak_server_cost,data,pos);
	 pos = setword(chargerecord->normal_server_pcs,data,pos);
	 pos = setword(chargerecord->normal_server_cost,data,pos);
	 pos = setword(chargerecord->valley_server_pcs,data,pos);
	 pos = setword(chargerecord->valley_server_cost,data,pos);
	 pos = setarray((uint8 *)chargerecord->orderno,8,data,pos);
	 
	 pos = add_head_length(data,pos);
   *len = pos;
	 
}
void probill_chargeauth(const struct t_up_authdata *authdata,uint8 *data,uint32 *len)
{
	  uint8 CMD = E_CMD_UP_CHARGE_AUTH;
    struct t_nw_asduhead asduhead;
    memset((uint8 *)&asduhead,0,sizeof(asduhead));

    uint8 objaddr[OBJADDR_LEN] = {0};
    memset(objaddr,0,sizeof(objaddr));

    uint32 pos = 0;

    GetConField(&asduhead.field,FRAME_TYPE_I);
    asduhead.type = E_TYPE_M_RE_NA_1;
    asduhead.vsq = GetVSQ(SQ_TYPE_NO_EQUAL, 1);//第二个参数要根据实际单点数据个数做修改
    asduhead.cot = getcmdcot(CMD);
    asduhead.publicaddr = getpublicaddr();

    pos = setbyte(asduhead.field.con1,data,pos);
    pos = setbyte(asduhead.field.con2,data,pos);
    pos = setbyte(asduhead.field.con3,data,pos);
    pos = setbyte(asduhead.field.con4,data,pos);

    pos = setbyte(asduhead.type,data,pos);
    pos = setbyte(asduhead.vsq,data,pos);
    pos = sethalfword(asduhead.cot,data,pos);
    pos = sethalfword(asduhead.publicaddr,data,pos);

    pos = setarray(objaddr,sizeof(objaddr),data,pos);

    pos = setbyte(CMD,data,pos);
    pos = setarray((uint8 *)authdata->devnum,8,data,pos);
    pos = setbyte(authdata->gunno,data,pos);
    pos = setarray((uint8 *)authdata->cardno,8,data,pos);
		pos = setarray((uint8 *)authdata->password,16,data,pos);
		pos = setarray((uint8 *)authdata->password_input,16,data,pos);
		pos = setword(authdata->card_remain,data,pos);	
    pos = sethalfword(authdata->card_state,data,pos);
		pos = setarray((uint8 *)authdata->carflag,32,data,pos);
		pos = setarray((uint8 *)authdata->costmodeno,8,data,pos);
		pos = setarray((uint8 *)authdata->paycardno,8,data,pos);
		pos = setarray((uint8 *)authdata->auth_paycard_data,8,data,pos);
		
    pos = add_head_length(data,pos);

    *len = pos;	
}
void probill_remotestart_ack(const struct t_up_remote_start_ack *ackdata,uint8 *data,uint32 *len )//启动应答
{
	 uint8 CMD = E_CMD_UP_REMOTE_START_CHARGE;
    struct t_nw_asduhead asduhead;
    memset((uint8 *)&asduhead,0,sizeof(asduhead));

    uint8 objaddr[OBJADDR_LEN] = {0};
    memset(objaddr,0,sizeof(objaddr));

    uint32 pos = 0;

    GetConField(&asduhead.field,FRAME_TYPE_I);
    asduhead.type = E_TYPE_M_RE_NA_1;
    asduhead.vsq = GetVSQ(SQ_TYPE_NO_EQUAL, 1);//第二个参数要根据实际单点数据个数做修改
    asduhead.cot = getcmdcot(CMD);
    asduhead.publicaddr = getpublicaddr();

    pos = setbyte(asduhead.field.con1,data,pos);
    pos = setbyte(asduhead.field.con2,data,pos);
    pos = setbyte(asduhead.field.con3,data,pos);
    pos = setbyte(asduhead.field.con4,data,pos);

    pos = setbyte(asduhead.type,data,pos);
    pos = setbyte(asduhead.vsq,data,pos);
    pos = sethalfword(asduhead.cot,data,pos);
    pos = sethalfword(asduhead.publicaddr,data,pos);

    pos = setarray(objaddr,sizeof(objaddr),data,pos);
		
 	  pos = setbyte(CMD,data,pos);
		pos = setarray((uint8 *)ackdata->devnum,8,data,pos);
  	pos = setbyte(ackdata->gunno,data,pos);
    pos = setarray((uint8 *)ackdata->trade_num,16,data,pos);
	  pos = setarray((uint8 *)ackdata->costmode,8,data,pos);
	  pos = setbyte(ackdata->startway,data,pos);
	  pos = setbyte(ackdata->result,data,pos);
   	pos = setbyte(ackdata->reason,data,pos);
	  pos = sethalfword(ackdata->max_total_v,data,pos);
	  pos = sethalfword(ackdata->max_total_i,data,pos);
	  pos = sethalfword(ackdata->battey_total_power,data,pos);
	  pos = setbyte(ackdata->max_temp,data,pos);
    pos = sethalfword(ackdata->single_battery_max_v,data,pos);
	  pos = sethalfword(ackdata->batterynow_v,data,pos);
	  pos = setarray((uint8 *)ackdata->userid,8,data,pos);
		
	  pos = add_head_length(data,pos);
    *len = pos;
}
void probill_remotestop_ack(const struct t_up_remote_stop_ack *ackdata,uint8 *data,uint32 *len )
{
	  uint8 CMD = E_CMD_UP_REMOTE_STOP_CHARGE;
    struct t_nw_asduhead asduhead;
    memset((uint8 *)&asduhead,0,sizeof(asduhead));

    uint8 objaddr[OBJADDR_LEN] = {0};
    memset(objaddr,0,sizeof(objaddr));

    uint32 pos = 0;

    GetConField(&asduhead.field,FRAME_TYPE_I);
    asduhead.type = E_TYPE_M_RE_NA_1;
    asduhead.vsq = GetVSQ(SQ_TYPE_NO_EQUAL, 1);//第二个参数要根据实际单点数据个数做修改
    asduhead.cot = getcmdcot(CMD);
    asduhead.publicaddr = getpublicaddr();

    pos = setbyte(asduhead.field.con1,data,pos);
    pos = setbyte(asduhead.field.con2,data,pos);
    pos = setbyte(asduhead.field.con3,data,pos);
    pos = setbyte(asduhead.field.con4,data,pos);

    pos = setbyte(asduhead.type,data,pos);
    pos = setbyte(asduhead.vsq,data,pos);
    pos = sethalfword(asduhead.cot,data,pos);
    pos = sethalfword(asduhead.publicaddr,data,pos);

    pos = setarray(objaddr,sizeof(objaddr),data,pos);
		
 	  pos = setbyte(CMD,data,pos);
		pos = setarray((uint8 *)ackdata->devnum,8,data,pos);
  	pos = setbyte(ackdata->gunno,data,pos);
		pos = setbyte(ackdata->flag,data,pos);
		
		 pos = add_head_length(data,pos);
    *len = pos;
}
void probill_remoteupdate_ack(const struct t_up_remote_updatestart_ack *ackdata,uint8 *data,uint32 *len)//远程升级应答
{
	  uint8 CMD = E_CMD_UP_REMOTE_UPDATE;
    struct t_nw_asduhead asduhead;
    memset((uint8 *)&asduhead,0,sizeof(asduhead));

    uint8 objaddr[OBJADDR_LEN] = {0};
    memset(objaddr,0,sizeof(objaddr));

    uint32 pos = 0;

    GetConField(&asduhead.field,FRAME_TYPE_I);
    asduhead.type = E_TYPE_M_RE_NA_1;
    asduhead.vsq = GetVSQ(SQ_TYPE_NO_EQUAL, 1);//第二个参数要根据实际单点数据个数做修改
    asduhead.cot = getcmdcot(CMD);
    asduhead.publicaddr = getpublicaddr();

    pos = setbyte(asduhead.field.con1,data,pos);
    pos = setbyte(asduhead.field.con2,data,pos);
    pos = setbyte(asduhead.field.con3,data,pos);
    pos = setbyte(asduhead.field.con4,data,pos);

    pos = setbyte(asduhead.type,data,pos);
    pos = setbyte(asduhead.vsq,data,pos);
    pos = sethalfword(asduhead.cot,data,pos);
    pos = sethalfword(asduhead.publicaddr,data,pos);

    pos = setarray(objaddr,sizeof(objaddr),data,pos);
		
 	  pos = setbyte(CMD,data,pos);
		pos = setarray((uint8 *)ackdata->devnum,8,data,pos);
		pos = setbyte(ackdata->flag,data,pos);
		
		 pos = add_head_length(data,pos);
    *len = pos;
}
